import { ESJMaterialType } from "earthsdk3";
import * as Cesium from 'cesium';
import { toCartesian3, toCartesian4 } from "./czmConverts";
import { ESCesiumViewer } from "@czmSrc/ESCesiumViewer";
import { createTextureFromImage } from "@czmSrc/CzmObjects";

export async function setModelMaterial(model: Cesium.Model, options: Omit<ESJMaterialType, 'baseColorTexture' | 'normalTexture' | "magFilter" | "minFilter"> & { baseColorTexture?: any, normalTexture?: any }) {
    //@ts-ignore
    const components = model.loader.components;
    components.nodes.forEach((node: any) => {
        node.primitives.forEach((primitive: any) => {
            options.baseColorFactor && (primitive.material.metallicRoughness.baseColorFactor = toCartesian4(options.baseColorFactor));
            options.alphaMode && (primitive.material.alphaMode = options.alphaMode); // 透明模式
            options.doubleSided && (primitive.material.doubleSided = options.doubleSided); // 双面
            options.unlit && (primitive.material.unlit = options.unlit); // 无光照
            options.emissiveFactor && (primitive.material.emissiveFactor = toCartesian3(options.emissiveFactor)); // 自发光
            options.metallicFactor && (primitive.material.metallicRoughness.metallicFactor = options.metallicFactor); // 金属度
            options.roughnessFactor && (primitive.material.metallicRoughness.roughnessFactor = options.roughnessFactor); // 平滑度
            options.baseColorTexture && (primitive.material.metallicRoughness.baseColorTexture = options.baseColorTexture);
            options.normalTexture && (primitive.material.metallicRoughness.normalTexture = options.normalTexture);
        })
    })
    //@ts-ignore
    model.resetDrawCommands(); // 重置drawCommands
}
export async function createTexture(czmViewer: ESCesiumViewer, colorTexture: ESJMaterialType['baseColorTexture'], options?: { magFilter?: string, minFilter?: string }) {
    let transform: any;
    const offset = colorTexture?.offset
        ? Cesium.Cartesian2.unpack(colorTexture.offset)
        : Cesium.Cartesian2.ZERO;
    let rotation = Cesium.defaultValue(colorTexture?.rotate, 0.0);
    const scale = colorTexture?.scale
        ? Cesium.Cartesian2.unpack(colorTexture?.scale)
        : new Cesium.Cartesian2(1.0, 1.0);

    // glTF assumes UV coordinates start with (0, 0) in the top left corner
    // (y-down) unlike WebGL which puts (0, 0) in the bottom left corner (y-up).
    // This means rotations are reversed since the angle from x to y is now
    // clockwise instead of CCW. Translations and scales are not impacted by
    // this.
    rotation = -rotation;

    // prettier-ignore
    transform = new Cesium.Matrix3(
        Math.cos(rotation) * scale.x, -Math.sin(rotation) * scale.y, offset.x,
        Math.sin(rotation) * scale.x, Math.cos(rotation) * scale.y, offset.y,
        0.0, 0.0, 1.0
    );
    //@ts-ignore
    const sampler = new Cesium.Sampler({
        minificationFilter: Cesium.TextureMinificationFilter[options?.minFilter as unknown as Cesium.TextureMinificationFilter || "LINEAR"],
        magnificationFilter: Cesium.TextureMagnificationFilter[options?.magFilter as unknown as Cesium.TextureMagnificationFilter || "LINEAR"],
    })
    //@ts-ignore
    return Cesium.Resource.createIfNeeded(colorTexture.value).fetchImage().then((image: HTMLImageElement) => {
        if (!czmViewer.viewer) return undefined;
        const texture = createTextureFromImage(czmViewer.viewer.scene.context, image);
        //@ts-ignore
        texture.sampler = sampler;
        //@ts-ignore
        const modelTextureReader = new Cesium.ModelComponents.TextureReader();
        modelTextureReader.index = 0;
        modelTextureReader.texture = texture;
        modelTextureReader.texCoord = 0;
        modelTextureReader.scale = undefined;
        modelTextureReader.transform = transform;
        modelTextureReader.channels = undefined;
        return modelTextureReader;
    });
}